﻿using NewAI.Game;
using NewAI.Tools;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NewAI.FSM.TankFSM
{
    public class RoundAnalyzer
    {
        TankAI entity;
        RoundData roundData;
        List<Point> aroundEnemyTankPos;
        List<Point> aroundOurTankPos;
        List<BulletAndDistance> aroundEnemyBulletsPos;//水平和竖直方向的子弹
        List<int> aroundEnemyTanksDistance;
        List<int> aroundOurTankDistance;
        List<CoinAndDistance> mapCoins;
        List<CoinAndDistance> aroundCoins;
        byte[,] elementsMap;
        byte[,] elementsMapWithBullet;
        Point nowTankPos;
        bool superBullet;

        float[,] threatMatrix;
        float[,] profitMatrix;


        List<byte[,]> ai_enemyBulletMap;//预测各个回合敌方子弹的的位置


        public class CoinAndDistance
        {
            public CoinAndDistance(Coin coin, int distance)
            {
                Coin = coin;
                Distance = distance;
            }
            public Coin Coin { set; get; }
            public int Distance { set; get; }
        }

        public class BulletAndDistance
        {
            public BulletAndDistance(Bullet bullet, int distance)
            {
                Bullet = bullet;
                Distance = distance;
            }

            public Bullet Bullet { set; get; }
            public int Distance { set; get; }
        }


        public void GetThreatDegreeAndProfitDegree(ref TankAI entity, ref RoundData roundData)
        {
            this.entity = entity;
            this.roundData = roundData;
            float totalWeight = TankAI.EnemyTanksDistanceThreatDegreeWeight;
            totalWeight += TankAI.BulletDistanceThreatDegreeWeight;
            totalWeight += TankAI.EnemyTanksCountThreatDegreeWeight;
            totalWeight += TankAI.OurTanksCountThreatDegreeWeight;
            totalWeight += TankAI.OurTanksDistanceThreatDegreeWeight;
            totalWeight += TankAI.RemainLifeThreatDegreeWeight;

            float tempThreat = 0f;
            float totalThreat = 0f;


            //敌人坦克距离+
            tempThreat = AnalyseAroundEnemyTankAverageDistanceThreatDegree();
            totalThreat = tempThreat * TankAI.EnemyTanksDistanceThreatDegreeWeight / totalWeight;

            //子弹威胁度+
            tempThreat = AnalyseBulletsThreatDegree();
            totalThreat = totalThreat + tempThreat * TankAI.BulletDistanceThreatDegreeWeight / totalWeight;

            //一定范围内敌方坦克数量+
            tempThreat = AroundEnemyTanksCountThreatDegree();
            totalThreat = totalThreat + tempThreat * TankAI.EnemyTanksCountThreatDegreeWeight / totalWeight;

            //一定范围内的友军数量-
            tempThreat = AroundOurTanksCountThreatDegree();
            totalThreat = totalThreat + tempThreat * TankAI.OurTanksCountThreatDegreeWeight / totalWeight;

            //一定范围内友军的平均距离-
            tempThreat = AroundOurTanksAverageDistanceThreatDegree();
            totalThreat = totalThreat + tempThreat * TankAI.OurTanksDistanceThreatDegreeWeight / totalWeight;

            //剩余复活次数+
            tempThreat = RemainLifeThreatDegree();
            totalThreat = totalThreat + tempThreat * TankAI.RemainLifeThreatDegreeWeight / totalWeight;

            entity.ThreatDegree = totalThreat * 100;

            //计算收益度
            SetProfitDegree();
        }

        public void SetProfitDegree()
        {
            float total = TankAI.AroundCoinsProfitDegreeWeight;
            total += TankAI.AroundCoinsValueProfitDegreeWeight;
            total += TankAI.KillTanksProfitDegreeWeight;

            float tempProfit = 0f; ;
            float totalProfit = 0f; ;

            //附近金币量个数收益度
            tempProfit = GetAroundCoinsProfitDegree();
            totalProfit = tempProfit * TankAI.AroundCoinsProfitDegreeWeight / total;

            //附近金币价值收益度
            tempProfit = AroundCoinsValueProfitDegree();
            totalProfit = totalProfit + tempProfit * TankAI.AroundCoinsValueProfitDegreeWeight / total;

            //能否一回合干掉坦克收益度
            tempProfit = KillTanksProfitDegree();
            totalProfit = totalProfit + tempProfit * TankAI.KillTanksProfitDegreeWeight / total;

            entity.ProfitDegree = totalProfit * 100;

            //传输数值
            SetBaseInfo();//TODO:要重命名函数以及优化调用顺序
        }

        public void SetBaseInfo()
        {
            entity.MyTankInfo = new TankInfo(entity.TankID, new Point(nowTankPos.X, nowTankPos.Y), superBullet);
            entity.TargetTankInfo = GetNearestAroundEnemyTankInfo();
            entity.TargetCoinInfo = GetNearestCoinInfo();
            AddAbsoluteDangerPointIntoMap();//计算周围的绝对危险点并加入到地图中
            entity.Map = elementsMapWithBullet;
            entity.TeamID = GV.OurTeam.TeamID;
            entity.ElementMap = GetGoodsMap();

            GetAroundEnemyBulletsPoint();
            entity.DangerousBulletInfo = new BulletInfo(GetNearestBulletPoint());

            entity.DefaultFightDirection = GetDefaultFightDirection();

            //TODO:Bug 可能出现在A*导航那里没有判断好0和1

            //TODO:下面的代码好像有个for循环没有把“i++”改成“i--”产生了死循环

            //TODO：特殊情况处理：有子弹向当前坦克射过来，但是当前坦克中间隔着砖墙
        }

        private Goods[,] GetGoodsMap()
        {
            Goods[,] tempGoodsMap = new Goods[GV.MapWidth, GV.MapHeight];
            foreach (var item in roundData.Goods)
                tempGoodsMap[item.Position.X, item.Position.Y] = item;
            return tempGoodsMap;
        }


        #region 矩阵操作
        /*
         s.GetLength(0) 返回第一维的长度（即行数）
         s.GetLength(1) 返回第二维的长度（即列数）
         i 上下移动
         j 左右移动
        */

        public static string GetMatrixString(float[,] matrix)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            string temp = "";
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                    if (j == 0)
                        temp += matrix[i, j].ToString();
                    else
                        temp += ("  " + (matrix[i, j]));
                temp += "\r\n";
            }
            return temp;
        }
        public static float[,] GetMatrix(int m, int n, float defaultValue = 0)
        {//先行数再列数
            float[,] temp = new float[m, n];
            for (int j = 0; j < n; j++)
                for (int i = 0; i < m; i++)
                    temp[i, j] = defaultValue;
            return temp;
        }
        public static float[,] MatrixAddition(float[,] matrixA, float[,] matrixB)
        {
            int m = matrixA.GetLength(0);
            int n = matrixA.GetLength(1);
            float[,] tempMatrix = GetMatrix(m, n, 0);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                    tempMatrix[i, j] = matrixA[i, j] + matrixB[i, j];
            }
            return tempMatrix;
        }
        public static float[,] MatrixSubtraction(float[,] matrixA, float[,] matrixB)
        {
            int m = matrixA.GetLength(0);
            int n = matrixA.GetLength(1);
            float[,] tempMatrix = GetMatrix(m, n, 0);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                    tempMatrix[i, j] = matrixA[i, j] - matrixB[i, j];
            }
            return tempMatrix;
        }
        public static float[,] AddMatrixPart(float[,] matrixA, float[,] matrixB, int add_i, int add_j)
        {
            int m = matrixB.GetLength(0);
            int n = matrixB.GetLength(1);
            float[,] temp = CopyMatrix(matrixA);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (IsOutOfMatrix(matrixA, i + add_i, j + add_j) == false)
                        temp[i + add_i, j + add_j] = matrixA[i + add_i, j + add_j] + matrixB[i, j];
                }
            }
            return temp;
        }
        public static float[,] CopyMatrix(float[,] matrix)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] temp = GetMatrix(m, n);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    temp[i, j] = matrix[i, j];
                }
            }
            return temp;
        }
        public static float[,] MatrixMultiplyByConstant(float[,] matrix, float constant)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] temp = GetMatrix(m, n);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    temp[i, j] = matrix[i, j] * constant;
                }
            }
            return temp;
        }
        public static float[,] MatrixConvert(byte[,] matrix)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] temp = GetMatrix(m, n);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    temp[i, j] = matrix[i, j];
                }
            }
            return temp;
        }
        public static float[,] MatrixConvert(int[,] matrix)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] temp = GetMatrix(m, n);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    temp[i, j] = matrix[i, j];
                }
            }
            return temp;
        }
        public static bool IsOutOfMatrix(float[,] matrix, int i, int j)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            if (i >= 0 && j >= 0 && i <= m - 1 && j <= n - 1)
                return false;
            return true;
        }
        public static float[,] SetMatrixMin(float[,] matrix, float min)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] temp = CopyMatrix(matrix);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (temp[i, j] < min)
                        temp[i, j] = min;
                }
            }
            return temp;
        }
        public static float[,] SetMatrixMax(float[,] matrix, float max)
        {
            int m = matrix.GetLength(0);
            int n = matrix.GetLength(1);
            float[,] temp = CopyMatrix(matrix);
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (temp[i, j] > max)
                        temp[i, j] = max;
                }
            }
            return temp;
        }
        #endregion

        #region 权值
        public static int enemyTankPositionThreatWeight = 50;   //敌人坦克位置
        public static int enemyTankBulletThreatWeight = 70;     //敌人坦克子弹

        #endregion

        #region 风险矩阵
        private float[,] GetThreatMatrix()
        {
            float total = enemyTankPositionThreatWeight;
            total += enemyTankBulletThreatWeight;

            float[,] matrix;
            matrix = Threat_EnemyTankPostition();
            matrix = MatrixMultiplyByConstant(matrix, enemyTankPositionThreatWeight / total);
            matrix = MatrixAddition(matrix, MatrixMultiplyByConstant(Threat_EnemyTankBullet(), enemyTankBulletThreatWeight / total));
            return matrix;
        }

        private float[,] enemyTankPostitionThreatMatrix =
          {
                {  5, 10, 20, 30, 20, 10,  5},
                { 10, 30, 40, 50, 40, 30, 10},
                { 20, 40, 70, 80, 70, 40, 20},
                { 30, 50, 80,100, 80, 50, 30},
                { 20, 40, 70, 80, 70, 40, 20},
                { 10, 30, 40, 50, 40, 30, 10},
                {  5, 10, 20, 30, 20, 10,  5}
            };
        private float[,] Threat_EnemyTankPostition()
        {
            float[,] matrix = GetMatrix(GV.MapWidth, GV.MapHeight, 0);

            //统计敌人坦克数量
            List<Player> enemyTanks = new List<Player>();
            foreach (var item in roundData.Players)
            {
                if (item.TeamID != GV.OurTeam.TeamID)
                    enemyTanks.Add(item);
            }
            if (enemyTanks.Count == 0)
                return matrix;

            //生成威胁矩阵图
            foreach (var item in roundData.Players)
            {
                if (item.TeamID != GV.OurTeam.TeamID)
                {
                    float[,] temp = MatrixMultiplyByConstant(enemyTankPostitionThreatMatrix, 0.7f);
                    matrix = AddMatrixPart(
                        matrix,
                        temp,
                        item.Position.Y - 3,
                        item.Position.X - 3
                        );
                }
            }

            enemyTanks.Clear();
            enemyTanks = null;
            return SetMatrixMax(matrix, 100);
        }

        private float[,] tankBulletThreatMatrix_Left = { { 100, 80, 60 } };
        private float[,] tankBulletThreatMatrix_Right = { { 60, 80, 100 } };
        private float[,] tankBulletThreatMatrix_Up = { { 100 }, { 80 }, { 60 } };
        private float[,] tankBulletThreatMatrix_Down = { { 60 }, { 80 }, { 100 } };
        private float[,] Threat_EnemyTankBullet()
        {
            float[,] matrix_nextRound = GetMatrix(GV.MapWidth, GV.MapHeight, 0);
            float[,] result = matrix_nextRound;
            //预测一回合子弹
            foreach (var item in roundData.Bullets)
            {
                if (item.TeamID != GV.OurTeam.TeamID)
                {
                    switch (item.Direction)
                    {
                        case Direction.Up:
                            matrix_nextRound = AddMatrixPart(matrix_nextRound, tankBulletThreatMatrix_Up, item.Position.Y - 2, item.Position.X);
                            break;
                        case Direction.Right:
                            matrix_nextRound = AddMatrixPart(matrix_nextRound, tankBulletThreatMatrix_Right, item.Position.Y, item.Position.X);
                            break;
                        case Direction.Down:
                            matrix_nextRound = AddMatrixPart(matrix_nextRound, tankBulletThreatMatrix_Down, item.Position.Y, item.Position.X);
                            break;
                        case Direction.Left:
                            matrix_nextRound = AddMatrixPart(matrix_nextRound, tankBulletThreatMatrix_Left, item.Position.Y, item.Position.X - 2);
                            break;
                        default:
                            break;
                    }
                }
            }
            float[,] matrix_someRounds = GetMatrix(GV.MapWidth, GV.MapHeight, 0);

            //将子弹模拟运动的结果加到威胁度矩阵中
            if (ai_enemyBulletMap.Count > 0)
            {
                for (int i = 0; i < ai_enemyBulletMap.Count; i++)
                {
                    float[,] temp = MatrixConvert(ai_enemyBulletMap[i]);
                    for (int y = 0; y < ai_enemyBulletMap[i].GetLength(1); y++)
                    {
                        for (int x = 0; x < ai_enemyBulletMap[i].GetLength(0); x++)
                        {
                            if (temp[x, y] == 1)
                                temp[x, y] = 0;
                            else
                                temp[x, y] = 1;
                        }
                    }

                    matrix_someRounds = MatrixAddition(
                        matrix_someRounds,
                        MatrixMultiplyByConstant(temp, 100 / ai_enemyBulletMap.Count)
                        );
                }
                matrix_someRounds = MatrixMultiplyByConstant(matrix_someRounds, 0.5f);
                result = MatrixAddition(matrix_nextRound, matrix_someRounds);
            }

            SetMatrixMax(result, 100f);
            return result;
        }

        private float[,] Threat_OurTankPosition()
        {
            return null;
        }

        private float[,] Threat_OurTankBullet()
        {
            return null;
        }

        private float[,] Threat_RemainLife()
        {
            return null;
        }


        #endregion


        private float[,] GetProfitMatrix()
        {
            float[,] matrix = InitTankProfitMatrix();

            return matrix;
        }


        #region 金矿收益矩阵

        private float[,] InitProfitMatrix()
        {
            float[,] mapCoinProfitMatrix = GetMatrix(GV.MapWidth, GV.MapHeight);
            foreach (var good in roundData.Goods)
            {
                if (good.ElementType == ElementType.Coin)
                {
                    float[,] coinProfitMatrix = GetAroundCoinProfitMatrix();
                    float ValueRate;
                    switch (((Coin)good).Point)
                    {
                        case 1: ValueRate = 0.6f; break;
                        case 2: ValueRate = 0.7f; break;
                        case 3: ValueRate = 0.8f; break;
                        case 4: ValueRate = 0.9f; break;
                        case 5: ValueRate = 1f; break;
                        default:
                            PubliceMessage.Debug("错误！，获取到的coin分值有问题");
                            ValueRate = 1f;
                            break;
                    }
                    coinProfitMatrix = MatrixMultiplyByConstant(coinProfitMatrix, ValueRate);
                    mapCoinProfitMatrix = AddMatrixPart(mapCoinProfitMatrix, coinProfitMatrix, good.Position.Y - 4, good.Position.X - 4);
                }
            }
            return mapCoinProfitMatrix;
        }

        private float[,] GetAroundCoinProfitMatrix()
        {
            float maxProfitInstance = 4 * 4 + 4 * 4;
            float[,] closeAroundMatrix = GetMatrix(9, 9);
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    float xPow2 = (i - 4) * (i - 4);
                    float yPow2 = (j - 4) * (j - 4);
                    if (i == 4 && j == 4)
                        closeAroundMatrix[j, i] = 100;
                    else
                        closeAroundMatrix[j, i] = maxProfitInstance / (xPow2 + yPow2) * 3;
                }
            }
            return closeAroundMatrix;
        }


        #endregion

        #region 超级子弹收益矩阵

        private float[,] InitSuperBulletProfitMatrix()
        {
            float[,] mapSuperBulletProfitMatrix = GetMatrix(GV.MapWidth, GV.MapHeight);
            foreach (var bullet in roundData.Bullets)
            {
                if (bullet.Type == BulletType.Super)
                {
                    float[,] superBulletProfitMatrix = GetAroundCoinProfitMatrix();
                    mapSuperBulletProfitMatrix = AddMatrixPart(mapSuperBulletProfitMatrix, superBulletProfitMatrix, bullet.Position.Y - 2, bullet.Position.X - 2);
                }
            }
            return mapSuperBulletProfitMatrix;
        }

        private float[,] GetAroundSuperBulletProfitMatrix()
        {
            float maxProfitInstance = 2 * 2 + 2 * 2;
            float[,] closeAroundMatrix = GetMatrix(5, 5);
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    float xPow2 = (i - 3) * (i - 3);
                    float yPow2 = (j - 3) * (j - 3);
                    if (i == 3 && j == 3)
                        closeAroundMatrix[3, 3] = 100;
                    else
                        closeAroundMatrix[j, i] = maxProfitInstance / (xPow2 + yPow2) * 11;
                }
            }
            return closeAroundMatrix;
        }


        #endregion

        #region 敌方tank收益矩阵


        private float[,] InitTankProfitMatrix()
        {
            float[,] mapCoinProfitMatrix = GetMatrix(GV.MapWidth, GV.MapHeight);
            foreach (var tank in roundData.Players)
            {
                if (tank.TeamID != GV.OurTeam.TeamID)
                {

                    mapCoinProfitMatrix = AddMatrixPart(mapCoinProfitMatrix, MatrixMultiplyByConstant(AllAroundMatrix, 0.4f), tank.Position.Y - 4, tank.Position.X - 4);
                }
            }

            return SetMatrixMax(mapCoinProfitMatrix, 100);
        }


        //private static float[,] AllAroundMatrix = 
        //    {
        //        {50,55,60,65,70,65,60,55,50 },
        //        {55,58,75,80,90,80,75,58,55 },
        //        {60,75,85,100,60,100,85,75,60 },
        //        {65,80,100,40,30,40,100,80,65 },
        //        {70,90,60,30,0,30,60,90,70 },
        //        {65,80,100,40,30,40,100,80,65 },
        //        {60,75,85,100,60,100,85,75,60 },
        //        {55,58,75,80,90,80,75,58,55 },
        //        {50,55,60,65,70,65,60,55,50 },
        //    };
        private static float[,] AllAroundMatrix =
            {
                {10,20,40,55,50,55,40,20,10 },
                {20,50,60,80,60,80,60,50,20 },
                {40,60,80,100,65,100,80,60,40 },
                {55,80,100,70,50,70,100,80,55},
                {50,75,65,50,0,50,65,75,50},
                {55,80,100,70,50,70,100,80,55 },
                {40,60,80,100,65,100,80,60,40 },
                {20,50,60,80,60,80,60,50,20 },
                {10,20,40,55,50,55,40,20,10 }
            };


        #endregion


        #region 提供默认移动方向以及子弹发射方向
        private DefaultFireAndMoveDirection GetDefaultFightDirection()
        {
            // 检查上下左右四个点是否可以走
            //估算危险度（含当前点），危险度小就往子弹方向走，
            //              危险度适中就不动
            //              危险度大就往危险度小的方向走
            var aroundPoint = GetAroundCanMovePoints();

            threatMatrix = GetThreatMatrix();
            profitMatrix = GetProfitMatrix();

            foreach (var item in aroundPoint)
            {
                item.Threat = threatMatrix[item.Point.X, item.Point.Y];
                item.Profit = profitMatrix[item.Point.X, item.Point.Y];
            }
            Direction? fire = null;
            Direction? move = null;

            SortAroundCanMovePointByTheart(ref aroundPoint);

            //向风险度最高的方向开火
            fire = TwoPointGetDirection(nowTankPos, aroundPoint[aroundPoint.Count - 1].Point);

            //向收益读最高的地方移动
            SortAroundCanMovePointByProfit(ref aroundPoint);
            if (move == null)
            {
                for (int i = aroundPoint.Count-1; i >=0 ; i--)
                {
                    if (aroundPoint[i].Threat<=10f)
                    {
                        move = TwoPointGetDirection(nowTankPos, aroundPoint[i].Point);
                        break;
                    }
                }
                if (move ==null)
                {
                    SortAroundCanMovePointByTheart(ref aroundPoint);
                    move= TwoPointGetDirection(nowTankPos, aroundPoint[0].Point);
                }
            }


           
            //if (fire == null)

            PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("ThreatMatrix", threatMatrix));
            PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("ProfitMatrix", profitMatrix));

            //var enemyTanks = GetMapEnemyTanks();
            //SetAroundCanMovePointsThreatAndProfit(ref aroundPoint, ref enemyTanks);

            //Direction? fire = null;
            //Direction? move = null;
            //SortAroundCanMovePointByTheart(ref aroundPoint);

            ////向风险度最高的方向开火
            //fire = TwoPointGetDirection(nowTankPos, aroundPoint[aroundPoint.Count - 1].Point);


            ////向风险度最低的方向移动
            //move = TwoPointGetDirection(nowTankPos, aroundPoint[0].Point);


            //entity.ThreatDegree = aroundPoint[aroundPoint.Count - 1].Threat;
            //entity.ProfitDegree = aroundPoint[0].Profit;

            //PubliceMessage.Debug($"Round ID = {entity.RoundID}");

            //if (entity.TankID == 1)
            //{
            //    string temp = "";
            //    for (int j = 0; j < 3; j++)
            //    {
            //        for (int y = 0; y < GV.MapHeight; y++)
            //        {
            //            for (int x = 0; x < GV.MapWidth; x++)
            //            {
            //                if (ai_enemyBulletMap[j][x, y] == 0)
            //                {
            //                    temp += "●";
            //                }
            //                else
            //                {
            //                    temp += "  ";
            //                }
            //            }
            //            temp += "\r\n";
            //        }
            //        temp += "\r\n";
            //    }
            //    PubliceMessage.Debug($"Round = {entity.RoundID} ,\r\n ————————\r\n{temp}");
            //}

            //if (entity.TankID == 1)
            //{
            //    string temp = "";
            //    for (int y = 0; y < GV.MapHeight; y++)
            //    {
            //        for (int x = 0; x < GV.MapWidth; x++)
            //        {
            //            if (elementsMap[x,y] == 0)
            //            {
            //                temp += "●";
            //            }
            //            else
            //            {
            //                temp += "  ";
            //            }
            //        }
            //        temp += "\r\n";
            //    }
            //    PubliceMessage.Debug($"Round = {entity.RoundID} ,\r\n ————————\r\n{temp}");
            //}



            return new DefaultFireAndMoveDirection(fire, move);
        }

        private void GetDefaultGetCoinDirection(out Direction? fire, out Direction? move)
        {
            // 检查上下左右四个点是否可以走
            // 检查这几个点是否有金矿，如果有则往金矿位置走，没有则进行下一步的判断
            // 计算金矿点的平均位置，往收益度高的方向走
            fire = null;
            move = null;
        }

        private void GetDefaultWithdrawDirection(out Direction? fire, out Direction? move)
        {
            //检查上下左右四个点是否可以走
            //估算危险度（含当前点），如果当前点危险度最低→不移动
            //否则往危险度最低的方向走
            fire = null;
            move = null;
        }

        private void GetDefaultAskForAssistanceDirection(out Direction? fire, out Direction? move)
        {
            //检查上下左右四个点是否可以走
            //估算危险度（含当前点），如果当前点危险度最低→不移动
            //否则往友军平均距离最大的方向走
            fire = null;
            move = null;
        }
        private Direction? TwoPointGetDirection(Point startPoint, Point endPoint)
        {
            if (startPoint.X == endPoint.X && startPoint.Y == endPoint.Y)
                return null;

            Direction? temp = new Direction();
            if (endPoint.X > startPoint.X)
                temp = Direction.Right;
            else if (endPoint.X < startPoint.X)
                temp = Direction.Left;
            else if (endPoint.Y > startPoint.Y)
                temp = Direction.Down;
            else if (endPoint.Y < startPoint.Y)
                temp = Direction.Up;
            return temp;
        }

        private void SortAroundCanMovePointByTheart(ref List<PointAndThreatAndProfitDegree> points)
        {
            if (points.Count <= 1)
                return;

            //冒泡排序（升序）
            PointAndThreatAndProfitDegree temp;
            for (int i = 0; i < points.Count; i++)
            {
                for (int j = i + 1; j < points.Count; j++)
                {
                    if (points[i].Threat > points[j].Threat)
                    {
                        temp = points[i];
                        points[i] = points[j];
                        points[j] = temp;
                    }
                }
            }
            //TODO:要测试冒泡排序的正确性
        }
        private void SortAroundCanMovePointByTheartPercentage(ref List<PointAndThreatAndProfitDegree> points)
        {
            if (points.Count <= 1)
                return;

            //冒泡排序（升序）
            PointAndThreatAndProfitDegree temp;
            for (int i = 0; i < points.Count; i++)
            {
                for (int j = i + 1; j < points.Count; j++)
                {
                    if (points[i].GetThreatPercentage() > points[j].GetThreatPercentage())
                    {
                        temp = points[i];
                        points[i] = points[j];
                        points[j] = temp;
                    }
                }
            }
            //TODO:要测试冒泡排序的正确性
        }

        private void SortAroundCanMovePointByProfit(ref List<PointAndThreatAndProfitDegree> points)
        {
            if (points.Count <= 1)
                return;

            //冒泡排序（升序）
            PointAndThreatAndProfitDegree temp;
            for (int i = 0; i < points.Count; i++)
            {
                for (int j = i + 1; j < points.Count; j++)
                {
                    if (points[i].Profit > points[j].Profit)
                    {
                        temp = points[i];
                        points[i] = points[j];
                        points[j] = temp;
                    }
                }
            }
            //TODO:要测试冒泡排序的正确性
        }
        private void SortAroundCanMovePointByProfitPercentage(ref List<PointAndThreatAndProfitDegree> points)
        {
            if (points.Count <= 1)
                return;

            //冒泡排序（升序）
            PointAndThreatAndProfitDegree temp;
            for (int i = 0; i < points.Count; i++)
            {
                for (int j = i + 1; j < points.Count; j++)
                {
                    if (points[i].GetProfitPercentage() > points[j].GetProfitPercentage())
                    {
                        temp = points[i];
                        points[i] = points[j];
                        points[j] = temp;
                    }
                }
            }
            //TODO:要测试冒泡排序的正确性
        }






        private List<PointAndThreatAndProfitDegree> GetAroundCanMovePoints(int bulletStep = 3)
        {
            //将上下左右四个点以及当前点，如果能走加入List
            List<PointAndThreatAndProfitDegree> temp = new List<PointAndThreatAndProfitDegree>();
            temp.Add(new PointAndThreatAndProfitDegree(new Point(nowTankPos.X, nowTankPos.Y)));

            if (NotOutOfMap(new Point(nowTankPos.X - 1, nowTankPos.Y)))
                temp.Add(new PointAndThreatAndProfitDegree(new Point(nowTankPos.X - 1, nowTankPos.Y)));
            if (NotOutOfMap(new Point(nowTankPos.X + 1, nowTankPos.Y)))
                temp.Add(new PointAndThreatAndProfitDegree(new Point(nowTankPos.X + 1, nowTankPos.Y)));
            if (NotOutOfMap(new Point(nowTankPos.X, nowTankPos.Y - 1)))
                temp.Add(new PointAndThreatAndProfitDegree(new Point(nowTankPos.X, nowTankPos.Y - 1)));
            if (NotOutOfMap(new Point(nowTankPos.X, nowTankPos.Y + 1)))
                temp.Add(new PointAndThreatAndProfitDegree(new Point(nowTankPos.X, nowTankPos.Y + 1)));
            return temp;
        }

        private bool CheckPointNotEnemyBullet(Point point, int step = 3)
        {
            if (NotOutOfMap(point) == false)//point不在地图内
                return true;

            for (int i = 0; i < step; i++)
                if (ai_enemyBulletMap[i][point.X, point.Y] == 0)
                    return false;
            return true;
        }



        private bool NotOutOfMap(Point point)
        {
            if (point.X >= 0 && point.X <= GV.MapWidth - 1 && point.Y >= 0 && point.Y <= GV.MapHeight - 1)
                return true;
            return false;
        }

        private void SetAroundCanMovePointsThreatAndProfit(ref List<PointAndThreatAndProfitDegree> points, ref List<Player> enemyTanks)
        {
            //注：收益算法：一般的风险再加上金矿收益
            foreach (var nowPoint in points)
            {
                float avgX = 0, avgY = 0;
                float sumX = 0, sumY = 0;
                foreach (var item in enemyTanks)
                {
                    sumX += (item.Position.X - nowPoint.Point.X);
                    sumY += (item.Position.Y - nowPoint.Point.X);
                }
                avgX = sumX / enemyTanks.Count;
                avgY = sumY / enemyTanks.Count;

                nowPoint.Threat = nowPoint.Threat + ((1 - avgX / 14) * 0.5f + (1 - avgY / 14) * 0.5f) * 100f;
                nowPoint.Profit = nowPoint.Threat * 0.5f;//一半的风险转化成收益
            }

            AddAroundCanMovePointsBulletsThreat(ref points);
            AddAroundCanMovePointsCoinProfit(ref points, ref enemyTanks);
        }

        private void AddAroundCanMovePointsCoinProfit(ref List<PointAndThreatAndProfitDegree> points, ref List<Player> enemyTanks)
        {
            foreach (var nowPoint in points)
            {
                if (mapCoins.Count == 0)
                    continue;

                float avgX = 0, avgY = 0;
                float sumX = 0, sumY = 0;
                int totalValue = 0;
                foreach (var item in mapCoins)
                {
                    sumX += (item.Coin.Position.X - nowPoint.Point.X);
                    sumY += (item.Coin.Position.Y - nowPoint.Point.X);
                    totalValue += item.Coin.Point;
                }

                avgX = sumX / mapCoins.Count;
                avgY = sumY / mapCoins.Count;
                nowPoint.Profit = nowPoint.Profit + (((1 - avgX / 14) * 0.5f + (1 - avgY / 14) * 0.5f) * 0.5f + totalValue * 0.5f) * 100f;
            }
        }

        private void AddAroundCanMovePointsBulletsThreat(ref List<PointAndThreatAndProfitDegree> points)
        {
            for (int i = 0; i < points.Count; i++)
            {
                for (int j = 0; j < ai_enemyBulletMap.Count; j++)
                {
                    if (ai_enemyBulletMap[j][points[i].Point.X, points[i].Point.Y] == 0)
                        points[i].Threat = points[i].Threat + (j + 1) * 10;
                }
            }
        }


        private List<Player> GetMapEnemyTanks()
        {
            List<Player> temp = new List<Player>();
            foreach (var item in roundData.Players)
                if (item.TeamID != GV.OurTeam.TeamID)
                    temp.Add(new Player(item.Id, item.TeamID, new Position(item.Position.X, item.Position.Y), item.HasSuperBullet));
            return temp;
        }

        private class PointAndThreatAndProfitDegree
        {
            public PointAndThreatAndProfitDegree(Point point, float threat, float profit)
            {
                Point = point;
                Threat = threat;
                Profit = profit;
            }
            public PointAndThreatAndProfitDegree(Point point)
            {
                Point = point;
            }
            public Point Point { set; get; }
            public float Threat { set; get; }//0~100
            public float Profit { set; get; }//0~100

            public float GetThreatPercentage()
            {
                float total = Threat + Profit;
                if (total == 0)
                    return -1;

                return Threat / total;
            }
            public float GetProfitPercentage()
            {
                float total = Threat + Profit;
                if (total == 0)
                    return -1;

                return Profit / total;
            }
        }

        public class DefaultFireAndMoveDirection
        {
            public DefaultFireAndMoveDirection()
            {

            }
            public DefaultFireAndMoveDirection(Direction? fire, Direction? move)
            {
                Fire = fire;
                Move = move;
            }
            public bool UseSuperBullet { set; get; }
            public Direction? Fire { set; get; }
            public Direction? Move { set; get; }
        }

        #endregion








        #region 获取周围子弹
        private Point GetNearestBulletPoint()
        {
            if (aroundEnemyBulletsPos == null || aroundEnemyBulletsPos.Count == 0)
                return new Point(-1, -1);


            //去除方向不一致的子弹
            for (int i = aroundEnemyBulletsPos.Count - 1; i >= 0; i--)
            {
                if (CheckOneBulletDirectionRight(aroundEnemyBulletsPos[i].Bullet) == false)
                    aroundEnemyBulletsPos.RemoveAt(i);
            }

            if (aroundEnemyBulletsPos.Count == 0)
                return new Point(-1, -1);

            //找最小值
            int min, minIndex;
            min = aroundEnemyBulletsPos[0].Distance;
            minIndex = 0;
            for (int i = 1; i < aroundEnemyBulletsPos.Count; i++)
            {
                if (min > aroundEnemyBulletsPos[i].Distance)
                {
                    min = aroundEnemyBulletsPos[i].Distance;
                    minIndex = i;
                }
            }

            return new Point(
                aroundEnemyBulletsPos[minIndex].Bullet.Position.X,
                aroundEnemyBulletsPos[minIndex].Bullet.Position.Y
                );
        }

        private bool CheckOneBulletDirectionRight(Bullet bullet)
        {
            switch (bullet.Direction)
            {
                case Direction.Up:
                    if (bullet.Position.Y >= nowTankPos.Y)
                        return true;
                    break;
                case Direction.Right:
                    if (bullet.Position.X <= nowTankPos.X)
                        return true;
                    break;
                case Direction.Down:
                    if (bullet.Position.Y <= nowTankPos.Y)
                        return true;
                    break;
                case Direction.Left:
                    if (bullet.Position.X >= nowTankPos.X)
                        return true;
                    break;
                default:
                    break;
            }
            return false;
        }

        private void GetAroundEnemyBulletsPoint()
        {
            aroundEnemyBulletsPos = new List<BulletAndDistance>();
            foreach (var item in roundData.Bullets)
            {
                if (item.TeamID == GV.OurTeam.TeamID)
                    continue;

                if (item.Position.X == nowTankPos.X || item.Position.Y == nowTankPos.Y)
                {
                    try
                    {
                        AStarPro.Astar(elementsMap, nowTankPos, new Point(item.Position.X, item.Position.Y), out List<Point> path);
                        aroundEnemyBulletsPos.Add(new BulletAndDistance(
                              new Bullet(item.Type, item.TeamID, item.Position, item.Direction),
                              path.Count
                              ));
                    }
                    catch (Exception)
                    {
                        //导航不到
                    }
                }
            }
        }
        #endregion

        #region 计算周围的绝对危险点并加入到地图中

        private void AddAbsoluteDangerPointIntoMap()
        {
            List<Point> dangerPoints = new List<Point>();
            foreach (var item in aroundEnemyTankPos)
                if (CheckOneEnemyPositionRight(item))
                    dangerPoints.Add(item);

            foreach (var item in dangerPoints)
                AddOneDangerPointIntoMap(item);
        }

        private bool CheckOneEnemyPositionRight(Point pos)
        {
            if (Math.Abs(pos.X - nowTankPos.X) <= 3 && Math.Abs(pos.Y - nowTankPos.Y) <= 3)
                return true;
            return false;
        }

        private void AddOneDangerPointIntoMap(Point enemyTankPos)
        {
            if (enemyTankPos.X - 2 >= 0)
            {
                elementsMap[enemyTankPos.X - 2, enemyTankPos.Y] = 0;
                elementsMapWithBullet[enemyTankPos.X - 2, enemyTankPos.Y] = 0;
            }
            if (enemyTankPos.X + 2 <= GV.MapWidth - 1)
            {
                elementsMap[enemyTankPos.X + 2, enemyTankPos.Y] = 0;
                elementsMapWithBullet[enemyTankPos.X + 2, enemyTankPos.Y] = 0;
            }
            if (enemyTankPos.Y - 2 >= 0)
            {
                elementsMap[enemyTankPos.X, enemyTankPos.Y - 2] = 0;
                elementsMapWithBullet[enemyTankPos.X, enemyTankPos.Y - 2] = 0;
            }
            if (enemyTankPos.Y + 2 <= GV.MapHeight - 1)
            {
                elementsMap[enemyTankPos.X, enemyTankPos.Y + 2] = 0;
                elementsMapWithBullet[enemyTankPos.X, enemyTankPos.Y + 2] = 0;
            }
        }


        #endregion



        #region 敌人坦克距离

        private float AnalyseAroundEnemyTankAverageDistanceThreatDegree()
        {
            float average = GetAroundEnemyTankAverageDistance(ref roundData);
            if (average >= 0)
                return average / TankAI.MaxEnemyDistance;
            return 0;
        }

        private float GetAroundEnemyTankAverageDistance(ref RoundData roundData)
        {
            GetNowTankPoint(out nowTankPos, out superBullet);
            aroundEnemyTankPos = GetAllEnemyTanksPoint();
            GetMapElementObstacleMap(out elementsMap, superBullet);

            //TODO:需要优化
            aroundEnemyTanksDistance = GetAllEnemyTanksDistance(ref aroundEnemyTankPos, ref elementsMap, ref nowTankPos);
            var average = GetAverageDistance(ref aroundEnemyTanksDistance);
            return average;
        }

        private void GetNowTankPoint(out Point pos, out bool superBullet)
        {
            foreach (var item in roundData.Players)
            {
                if (item.Id == entity.TankID)
                {
                    pos = new Point(item.Position.X, item.Position.Y);
                    superBullet = item.HasSuperBullet;
                    return;
                }
            }
            superBullet = false;
            pos = new Point(-1, -1);
        }

        private List<Point> GetAllEnemyTanksPoint()
        {
            List<Point> enemyTanksPoint = new List<Point>();
            foreach (var item in roundData.Players)
            {
                if (item.TeamID != GV.OurTeam.TeamID)
                    enemyTanksPoint.Add(new Point(item.Position.X, item.Position.Y));
            }
            return enemyTanksPoint;
        }

        //注：如果该坦克有超级子弹的话将会把铁墙设置成可通行道路
        private void GetMapElementObstacleMap(out byte[,] map, bool superBullet)
        {
            map = new byte[GV.MapWidth, GV.MapHeight];
            for (int j = 0; j < GV.MapHeight; j++)
            {
                for (int i = 0; i < GV.MapWidth; i++)
                    map[i, j] = 1;
            }
            int nowValue;
            foreach (var item in roundData.Goods)
            {
                switch (item.ElementType)
                {
                    case ElementType.BrickWall:
                        nowValue = 2;
                        break;
                    case ElementType.IronWall:
                        nowValue = (byte)(superBullet == true ? 2 : 0);
                        break;
                    case ElementType.River:
                        nowValue = 0;
                        break;
                    case ElementType.Coin:
                        nowValue = 1;
                        break;
                    case ElementType.Star:
                        nowValue = 1;
                        break;
                    case ElementType.Nothing:
                        nowValue = 1;
                        break;
                    default:
                        nowValue = 1;
                        break;
                }
                map[item.Position.X, item.Position.Y] = (byte)nowValue;
            }

        }

        private List<int> GetAllEnemyTanksDistance(ref List<Point> enemyTanksPoint, ref byte[,] map, ref Point myPoint)
        {

            #region A星距离
            //List<int> distance = new List<int>();
            //foreach (var item in enemyTanksPoint)
            //{
            //    try
            //    {
            //        AStarPro.Astar(map, myPoint, item, out List<Point> tempPath);
            //        distance.Add(tempPath.Count);
            //        tempPath.Clear();
            //    }
            //    catch (Exception)
            //    {
            //        distance.Add(-1);
            //    }
            //}
            //return distance;
            #endregion

            #region 直角距离
            List<int> distance = new List<int>();
            foreach (var item in enemyTanksPoint)
            {
                try
                {
                    distance.Add(Math.Abs(nowTankPos.X - item.X) + Math.Abs(nowTankPos.Y - item.Y));
                }
                catch (Exception)
                {
                    distance.Add(-1);
                }
            }
            return distance;
            #endregion

        }

        private float GetAverageDistance(ref List<int> distance)
        {
            int sum = 0;
            int count = 0;
            for (int i = 0; i < distance.Count; i++)
            {
                if (distance[i] != -1 && distance[i] <= TankAI.MaxEnemyDistance)
                {
                    sum += distance[i];
                    count++;
                }
            }
            if (count == 0)
                return -1;

            //注：单精度浮点数效率高
            return (float)sum / count;
        }

        private TankInfo GetNearestAroundEnemyTankInfo()
        {
            int min = -1;
            int minIndex = -1;

            //TODO:应该增加获取敌人坦克是否有超级子弹的函数
            if (aroundEnemyTankPos.Count == 0)
                return new TankInfo(entity.TankID, new Point(-1, -1), false);

            for (int i = 0; i < aroundEnemyTankPos.Count; i++)
            {
                if (aroundEnemyTanksDistance[i] != -1)
                {
                    if (min == -1)//第一项
                    {
                        min = aroundEnemyTanksDistance[i];
                        minIndex = i;
                    }
                    else if (min > aroundEnemyTanksDistance[i])//其他项
                    {
                        min = aroundEnemyTanksDistance[i];
                        minIndex = i;
                    }
                }
            }

            if (minIndex == -1)
                return new TankInfo(entity.TankID, new Point(-1, -1), superBullet);
            //TODO:应该增加获取敌人坦克是否有超级子弹的函数
            return new TankInfo(entity.TankID, new Point(aroundEnemyTankPos[minIndex].X, aroundEnemyTankPos[minIndex].Y), false);
        }

        #endregion

        #region 子弹威胁度



        private float AnalyseBulletsThreatDegree()
        {
            InitBulletsMap(out Bullet[,] currentEnemyBulletsMap, out Bullet[,] currentOurBulletsMap);
            InitElementsMapWithBullet();
            int distance = 0;
            for (int i = 0; i < 3 * TankAI.MaxForecastBulletsMoveRound; i++)
            {
                if (AnalyseBulletsOneStep(ref currentEnemyBulletsMap, ref currentOurBulletsMap))
                {
                    if (distance == 0)
                        distance = i + 1;//仅保存最短距离
                }
                if (i < 3)
                {
                    AddAIEnemyBulletMap();
                    AddCurrentEnemyBulletsIntoOneAIEnemyBulletMap(ref currentEnemyBulletsMap, ai_enemyBulletMap[ai_enemyBulletMap.Count - 1]);
                }
                if (i < 2)
                    AddCurrentBulletMap(ref currentEnemyBulletsMap);
            }
            return (float)distance / (3 * TankAI.MaxForecastBulletsMoveRound);
        }


        private void AddAIEnemyBulletMap()
        {
            if (ai_enemyBulletMap == null)
                ai_enemyBulletMap = new List<byte[,]>();

            byte[,] temp = new byte[GV.MapWidth, GV.MapHeight];
            for (int y = 0; y < GV.MapHeight; y++)
                for (int x = 0; x < GV.MapWidth; x++)
                    temp[x, y] = 1;
            ai_enemyBulletMap.Add(temp);
        }

        private void AddCurrentEnemyBulletsIntoOneAIEnemyBulletMap(ref Bullet[,] currentEnemyBulletsMap, byte[,] AIEnemyBulletMap)
        {
            for (int y = 0; y < GV.MapHeight; y++)
            {
                for (int x = 0; x < GV.MapWidth; x++)
                {
                    if (currentEnemyBulletsMap[x, y] != null)
                        AIEnemyBulletMap[x, y] = 0;
                }
            }
        }


        private void InitBulletsMap(out Bullet[,] currentEnemyBulletsMap, out Bullet[,] currentOurBulletsMap)
        {
            currentEnemyBulletsMap = new Bullet[GV.MapWidth, GV.MapHeight];
            currentOurBulletsMap = new Bullet[GV.MapWidth, GV.MapHeight];

            //将子弹加入地图中
            foreach (var item in roundData.Bullets)
            {
                if (item.TeamID == GV.OurTeam.TeamID)
                    currentOurBulletsMap[item.Position.X, item.Position.Y] = new Bullet(item.Type, item.TeamID, new Position(item.Position.X, item.Position.Y), item.Direction);
                else
                    currentEnemyBulletsMap[item.Position.X, item.Position.Y] = new Bullet(item.Type, item.TeamID, new Position(item.Position.X, item.Position.Y), item.Direction);
            }
        }

        //子弹移动一格，true = 在当前回合的该步骤本坦克被击毙
        private bool AnalyseBulletsOneStep(ref Bullet[,] currentEnemyBulletsMap, ref Bullet[,] currentOurBulletsMap)
        {
            //TODO:可能要增加检查前面是否有友军挡子弹
            //TODO:要增加检查子弹重叠数量
            Bullet[,] nextEnemyBulletsMap = new Bullet[GV.MapWidth, GV.MapHeight];
            Bullet[,] nextOurBulletsMap = new Bullet[GV.MapWidth, GV.MapHeight];

            //敌人子弹移动一格
            for (int j = 0; j < GV.MapHeight; j++)
            {
                for (int i = 0; i < GV.MapWidth; i++)
                {
                    if (elementsMap[i, j] == 2)//当前该位置不可能有子弹
                        continue;
                    if (currentEnemyBulletsMap[i, j] != null)
                    {
                        switch (currentEnemyBulletsMap[i, j].Direction)
                        {
                            case Direction.Up:
                                if (j - 1 >= 0)
                                    nextEnemyBulletsMap[i, j - 1] = currentEnemyBulletsMap[i, j];
                                break;
                            case Direction.Right:
                                if (i + 1 <= GV.MapWidth - 1)
                                    nextEnemyBulletsMap[i + 1, j] = currentEnemyBulletsMap[i, j];
                                break;
                            case Direction.Down:
                                if (j + 1 <= GV.MapHeight - 1)
                                    nextEnemyBulletsMap[i, j + 1] = currentEnemyBulletsMap[i, j];
                                break;
                            case Direction.Left:
                                if (i - 1 >= 0)
                                    nextEnemyBulletsMap[i - 1, j] = currentEnemyBulletsMap[i, j];
                                break;
                            default:
                                break;
                        }
                    }
                }
            }

            //我方子弹移动一格
            for (int j = 0; j < GV.MapHeight; j++)
            {
                for (int i = 0; i < GV.MapWidth; i++)
                {
                    if (elementsMap[i, j] == 2)//当前该位置不可能有子弹
                        continue;
                    if (currentOurBulletsMap[i, j] != null)
                    {
                        switch (currentOurBulletsMap[i, j].Direction)
                        {
                            case Direction.Up:
                                if (j - 1 >= 0)
                                    nextOurBulletsMap[i, j - 1] = currentOurBulletsMap[i, j];
                                break;
                            case Direction.Right:
                                if (i + 1 <= GV.MapWidth - 1)
                                    nextOurBulletsMap[i + 1, j] = currentOurBulletsMap[i, j];
                                break;
                            case Direction.Down:
                                if (j + 1 <= GV.MapHeight - 1)
                                    nextOurBulletsMap[i, j + 1] = currentOurBulletsMap[i, j];
                                break;
                            case Direction.Left:
                                if (i - 1 >= 0)
                                    nextOurBulletsMap[i - 1, j] = currentOurBulletsMap[i, j];
                                break;
                            default:
                                break;
                        }
                    }
                }
            }

            //检查两个子弹是否对撞
            for (int j = 0; j < GV.MapHeight; j++)
            {
                for (int i = 0; i < GV.MapWidth; i++)
                {
                    if (nextEnemyBulletsMap[i, j] != null && nextOurBulletsMap[i, j] != null)
                    {
                        nextEnemyBulletsMap[i, j] = null;
                        nextOurBulletsMap[i, j] = null;
                    }
                }
            }

            currentEnemyBulletsMap = nextEnemyBulletsMap;
            currentOurBulletsMap = nextOurBulletsMap;

            return currentEnemyBulletsMap[nowTankPos.X, nowTankPos.Y] != null;
        }

        private void InitElementsMapWithBullet()
        {
            elementsMapWithBullet = new byte[elementsMap.GetLength(0), elementsMap.GetLength(1)];

            //复制一份地图
            for (int j = 0; j < elementsMap.GetLength(1); j++)
                for (int i = 0; i < elementsMap.GetLength(0); i++)
                    elementsMapWithBullet[i, j] = elementsMap[i, j];
        }

        //将子弹地图与障碍物地图合并
        private void AddCurrentBulletMap(ref Bullet[,] currentEnemyBulletsMap)
        {
            for (int j = 0; j < GV.MapHeight; j++)
            {
                for (int i = 0; i < GV.MapWidth; i++)
                {
                    //有敌方子弹，标记为不能走
                    if (currentEnemyBulletsMap[i, j] != null && currentEnemyBulletsMap[i, j].TeamID != GV.OurTeam.TeamID)
                        elementsMapWithBullet[i, j] = 0;
                }
            }
        }


        #endregion

        #region 一定范围内敌方坦克数量

        private float AroundEnemyTanksCountThreatDegree()
        {
            int count = 0;
            foreach (var item in aroundEnemyTanksDistance)
            {
                if (item != -1 && item <= TankAI.MaxAroundEnemyTankDistance)
                    count++;
            }

            float threat = 0;
            switch (count)
            {
                case 1:
                    threat = 0.1f;
                    break;
                case 2:
                    threat = 0.4f;
                    break;
                case 3:
                    threat = 0.8f;
                    break;
                case 4:
                    threat = 1;
                    break;
            }
            return threat;
        }

        #endregion

        #region 一定范围内的友军数量
        private float AroundOurTanksCountThreatDegree()
        {
            GetOurTanksPoint();
            GetOurTanksDistance();

            int count = 0;
            foreach (var item in aroundOurTankDistance)
            {
                if (item > 0 && item <= TankAI.MaxAroundOurTankDistance)
                    count++;
            }

            float threat;
            switch (count)
            {
                case 0:
                    threat = 1f;
                    break;
                case 1:
                    threat = 0.8f;
                    break;
                case 2:
                    threat = 0.4f;
                    break;
                case 3:
                    threat = 0.1f;
                    break;
                default:
                    threat = 1f;
                    break;
            }
            return threat;
        }

        private void GetOurTanksPoint()
        {
            aroundOurTankPos = new List<Point>();
            foreach (var item in roundData.Players)
            {
                if (item.TeamID == GV.OurTeam.TeamID && item.Id != entity.TankID)//排除自己
                    aroundOurTankPos.Add(new Point(item.Position.X, item.Position.Y));
            }
        }

        private void GetOurTanksDistance()
        {

            #region A星距离
            //List<Point> path;
            //aroundOurTankDistance = new List<int>();
            //foreach (var item in aroundOurTankPos)
            //{
            //    try
            //    {
            //        AStarPro.Astar(elementsMap, nowTankPos, item, out path);
            //        aroundOurTankDistance.Add(path.Count);
            //        path.Clear();
            //    }
            //    catch (Exception)
            //    {
            //        aroundOurTankDistance.Add(-1);
            //    }
            //}
            #endregion


            #region 直角距离
            List<Point> path;
            aroundOurTankDistance = new List<int>();
            foreach (var item in aroundOurTankPos)
                aroundOurTankDistance.Add(Math.Abs(nowTankPos.X - item.X) + Math.Abs(nowTankPos.Y - item.Y));
            #endregion

        }

        #endregion

        #region 一定范围内友军的平均距离
        private float AroundOurTanksAverageDistanceThreatDegree()
        {
            int count = 0;
            int sum = 0;
            float average = 0; ;
            foreach (var item in aroundOurTankDistance)
            {
                if (item > 0 && item < TankAI.MaxAroundOurTankDistance)
                {
                    count++;
                    sum += item;
                }
            }
            if (count == 0)
                return 1;

            average = sum / count;
            return average / TankAI.MaxAroundOurTankDistance;
        }
        #endregion

        #region 剩余复活次数
        private float RemainLifeThreatDegree()
        {
            float threat = 0;
            foreach (var item in roundData.Teams)
            {
                if (item.TeamID == GV.OurTeam.TeamID)
                {
                    switch (item.RemainLife + GetOurTanksCount())
                    {
                        case 0:
                            threat = 1f;
                            break;
                        case 1:
                            threat = 0.875f;
                            break;
                        case 2:
                            threat = 0.75f;
                            break;
                        case 3:
                            threat = 0.625f;
                            break;
                        case 4:
                            threat = 0.5f;
                            break;
                        case 5:
                            threat = 0.375f;
                            break;
                        case 6:
                            threat = 0.25f;
                            break;
                        case 7:
                            threat = 0.125f;
                            break;
                        case 8:
                            threat = 0f;
                            break;
                    }
                    break;
                }
            }
            return threat;
        }

        private int GetOurTanksCount()
        {
            int count = 0;
            foreach (var item in roundData.Players)
            {
                if (item.TeamID == GV.OurTeam.TeamID)
                    count++;
            }
            return count;
        }

        #endregion


        #region 附近金币量个数收益度
        private float GetAroundCoinsProfitDegree()
        {
            GetCornsList();
            GetAroundCoins();
            if (mapCoins.Count != 0)
                return (float)aroundCoins.Count / mapCoins.Count;
            return 0f;
        }

        private void GetCornsList()
        {
            mapCoins = new List<CoinAndDistance>();
            foreach (var item in roundData.Goods)
            {
                if (item.ElementType == ElementType.Coin)
                    mapCoins.Add(GetCornAndDistance(item as Coin));
            }
        }

        private void GetAroundCoins()
        {
            aroundCoins = new List<CoinAndDistance>();
            foreach (var item in mapCoins)
            {
                if (item.Distance != -1 && item.Distance <= TankAI.MaxAroundCoinDistance)
                    aroundCoins.Add(item);
            }
        }

        private CoinAndDistance GetCornAndDistance(Coin coin)
        {

            #region A星距离
            //try
            //{
            //    AStarPro.Astar(elementsMap, nowTankPos, new Point(coin.Position.X, coin.Position.Y), out List<Point> path);
            //    return new CoinAndDistance(coin, path.Count);
            //}
            //catch (Exception)
            //{
            //    return new CoinAndDistance(coin, -1);
            //}
            #endregion

            #region 直角距离

            return new CoinAndDistance(coin, Math.Abs(nowTankPos.X - coin.Position.X) + Math.Abs(nowTankPos.Y - coin.Position.Y));

            #endregion


        }

        private CoinInfo GetNearestCoinInfo()
        {
            int min = -1, minIndex = -1;
            for (int i = 0; i < aroundCoins.Count; i++)
            {
                if (aroundCoins[i].Distance != -1)
                {
                    if (min == -1)//第一项
                    {
                        min = aroundCoins[i].Distance;
                        minIndex = i;
                    }
                    else if (min > aroundCoins[i].Distance)
                    {
                        min = aroundCoins[i].Distance;
                        minIndex = i;
                    }
                }
            }
            if (min == -1 || minIndex == -1)
                return new CoinInfo(new Point(-1, -1));
            else
                return new CoinInfo(new Point(aroundCoins[minIndex].Coin.Position.X, aroundCoins[minIndex].Coin.Position.Y));
        }

        #endregion

        #region 附近金币价值收益度
        private float AroundCoinsValueProfitDegree()
        {
            if (mapCoins.Count == 0 || aroundCoins.Count == 0)
                return 0;

            int mapCoinsValue = 0;
            int aroundCoinsValue = 0;

            foreach (var item in mapCoins)
                mapCoinsValue += item.Coin.Point;

            foreach (var item in aroundCoins)
                aroundCoinsValue += item.Coin.Point;

            if (mapCoinsValue != 0)
                return (float)aroundCoinsValue / mapCoinsValue;
            return 0;

        }
        #endregion

        #region 能否一回合干掉坦克收益度
        private float KillTanksProfitDegree()
        {
            bool can = CanKillTanksInOneRound();
            return (can ? 1f : 0);
        }

        private bool CanKillTanksInOneRound()
        {
            //向上
            if (nowTankPos.Y - 2 >= 0)
            {
                if (nowTankPos.X - 1 >= 0)//左上方
                {
                    if (elementsMap[nowTankPos.X, nowTankPos.Y - 1] != 0 &&
                        elementsMap[nowTankPos.X, nowTankPos.Y - 2] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X - 1, nowTankPos.Y - 2))
                        )
                        return true;
                }
                else if (nowTankPos.X + 1 <= GV.MapWidth - 1)//右上方
                {
                    if (elementsMap[nowTankPos.X, nowTankPos.Y - 1] != 0 &&
                        elementsMap[nowTankPos.X, nowTankPos.Y - 2] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X + 1, nowTankPos.Y - 2))
                        )
                        return true;
                }
            }

            //向下
            if (nowTankPos.Y + 2 <= GV.MapHeight - 1)
            {
                if (nowTankPos.X - 1 >= 0)//左下方
                {
                    if (elementsMap[nowTankPos.X, nowTankPos.Y + 1] != 0 &&
                        elementsMap[nowTankPos.X, nowTankPos.Y + 2] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X - 1, nowTankPos.Y + 2))
                        )
                        return true;
                }
                else if (nowTankPos.X + 1 <= GV.MapWidth - 1)//右下方
                {
                    if (elementsMap[nowTankPos.X, nowTankPos.Y + 1] != 0 &&
                        elementsMap[nowTankPos.X, nowTankPos.Y + 2] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X + 1, nowTankPos.Y + 2))
                        )
                        return true;
                }
            }

            //向左
            if (nowTankPos.X - 2 >= 0)
            {
                if (nowTankPos.Y - 1 >= 0)//左边上方
                {
                    if (elementsMap[nowTankPos.X - 1, nowTankPos.Y] != 0 &&
                        elementsMap[nowTankPos.X - 2, nowTankPos.Y] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X - 2, nowTankPos.Y - 1))
                        )
                        return true;
                }
                else if (nowTankPos.Y + 1 <= GV.MapHeight - 1)//左边下方
                {
                    if (elementsMap[nowTankPos.X - 1, nowTankPos.Y] != 0 &&
                        elementsMap[nowTankPos.X - 2, nowTankPos.Y] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X - 2, nowTankPos.Y + 1))
                        )
                        return true;
                }
            }

            //向右
            if (nowTankPos.X + 2 <= GV.MapWidth - 1)
            {
                if (nowTankPos.Y - 1 >= 0)//右边上方
                {
                    if (elementsMap[nowTankPos.X + 1, nowTankPos.Y] != 0 &&
                        elementsMap[nowTankPos.X + 2, nowTankPos.Y] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X + 2, nowTankPos.Y - 1))
                        )
                        return true;
                }
                else if (nowTankPos.Y + 1 <= GV.MapHeight - 1)//右边下方
                {
                    if (elementsMap[nowTankPos.X + 1, nowTankPos.Y] != 0 &&
                        elementsMap[nowTankPos.X + 2, nowTankPos.Y] != 0 &&
                        aroundEnemyTankPos.Contains(new Point(nowTankPos.X + 2, nowTankPos.Y + 1))
                        )
                        return true;
                }
            }
            return false;
        }

        #endregion
    }
}
